home *** CD-ROM | disk | FTP | other *** search
- #include "main.h"
- #include "patch.h"
- #include "patch.menu.h"
-
- /*******************************************************
- * *
- * This currently works with : *
- * normal menu selection. *
- * heierarchical menu selection. *
- * pop-up menu selection in DAs *
- * Should work with, but doesn't: *
- * tear-off menus, installed by other inits and things. *
- * Known problems: *
- * may mess up with icons in menus. *
- * may mess up with Pop-Up Menus in modal dialogs brought up by DAs. *
- * *
- *******************************************************/
-
- extern long timer();
-
- long oldPopUp, oldDragGray, oldDragThe, oldWaitMouse,
- oldSysMenu, oldStillDown, oldAvail, oldDelay, oldCopyBits;
- int menuTrapsOn = 0, waitTrapOn = 0, popUpTrapOn = 0,
- sysMenuActed = 0, delayTrapOn = 0;
- int isMyCopy = 1;
-
- static rgnListHandle menuRgns = NULL;
-
- /*******************************************************
- * *
- * *
- *******************************************************/
-
- WindowPeek nextUserWindow( theWindow )
- WindowPeek theWindow;
- {
- while( theWindow && theWindow->windowKind < userKind )
- theWindow = theWindow->nextWindow;
- return( theWindow );
- }
-
- /* Trouble here - dest may be either a BitMapPtr or a PixMapPtr. */
-
- fixWindows( dest, bounds, menuMask, when )
- BitMap *dest;
- Rect *bounds;
- RgnHandle menuMask;
- long when;
- {
- Rect realBounds;
- Point off;
- GrafPtr savePort;
- WindowPeek theWindow;
- RgnHandle mask, selMask;
- dataHandle theDataHand;
- dataPtr theData;
-
- mask = NewRgn();
- selMask = NewRgn();
- theWindow = nextUserWindow( FrontWindow() );
- GetPort( &savePort );
- while( theWindow ) {
- theDataHand = ( dataHandle )GetWRefCon( theWindow );
- HLock( theDataHand );
- theData = *theDataHand;
- if( theData->changed > when ) {
- off = topLeft( theWindow->port.portBits.bounds );
- SectRgn( theWindow->port.visRgn, theWindow->port.clipRgn, mask );
- OffsetRgn( mask, -off.h, -off.v );
- SectRgn( menuMask, mask, mask );
- if( !EmptyRgn( mask )) {
- if( theData->allBitsState ) {
- SetPort( theWindow );
- fixAllBits( theData );
- SetPort( savePort );
- }
- doMenuCopy( &( theData->allBits ), dest, bounds, mask, off );
- }
- }
- HUnlock( theDataHand );
- theWindow = nextUserWindow( theWindow->nextWindow );
- }
- DisposeRgn( mask );
- DisposeRgn( selMask );
- }
-
- doMenuCopy( source, dest, bounds, mask, off )
- BitMap *source, *dest;
- Rect *bounds;
- RgnHandle mask;
- Point off;
- {
- Rect tempRect;
-
- OffsetRect( &( source->bounds ), -off.h, -off.v );
- if( SectRect( &( source->bounds ), bounds, &tempRect ))
- CopyBits( source, dest, &tempRect, &tempRect, srcCopy, mask );
- OffsetRect( &( source->bounds ), off.h, off.v );
- }
-
- /*******************************************************
- * *
- * *
- *******************************************************/
-
- isScreen( map )
- BitMap *map;
- {
- if( map->rowBytes & 0x8000 )
- return((( PixMapPtr )map )->baseAddr == ( **( **GetGDevice() ).gdPMap ).baseAddr );
- else return( map->baseAddr == screenBits.baseAddr );
- }
-
- /*******************************************************
- * *
- * *
- *******************************************************/
-
- BitMap *fixPixPtr( thePtr )
- BitMap *thePtr;
- {
- if(( thePtr->rowBytes & 0xc000 ) == 0xc000 )
- thePtr = *( BitMap ** )( thePtr->baseAddr );
- return( thePtr );
- }
-
- fixCopy( source, dest, sRect, dRect, mode, mask )
- BitMap *source, *dest;
- Rect *sRect, *dRect;
- int mode;
- RgnHandle mask;
- {
- Rect realRect;
- RgnHandle tempRgn, menuRgn;
- rgnListHandle theList;
- rgnListPtr rgns;
- int sScreen, dScreen, errno;
-
- source = fixPixPtr( source );
- dest = fixPixPtr( dest );
- sScreen = isScreen( source );
- dScreen = isScreen( dest );
- if( sScreen && !dScreen )
- {
- tempRgn = NewRgn();
- menuRgn = NewRgn();
- realRect = *sRect;
- realRect.left += 3;
- realRect.bottom -= 3;
- realRect.right -= 3;
- RectRgn( menuRgn, &realRect );
- realRect.bottom += 1;
- realRect.right += 1;
- realRect.left += 3;
- RectRgn( tempRgn, &realRect );
- UnionRgn( tempRgn, menuRgn, menuRgn );
- DisposeRgn( tempRgn );
- theList = ( rgnListHandle )NewHandle(( long )sizeof( rgnList ));
- if( errno = MemError() ) hardPanic( errno, memPanic );
- if( menuRgns ) UnionRgn(( **menuRgns ).theRgn, menuRgn, menuRgn );
- rgns = *theList;
- rgns->next = menuRgns;
- rgns->theRgn = menuRgn;
- rgns->origRect = *sRect;
- rgns->when = timer();
- menuRgns = theList;
- }
- else if( dScreen && !sScreen )
- {
- if( EqualRect( dRect, &(( **menuRgns ).origRect ))) /* We must be undo-ing the last menu pull-down */
- {
- HLock( menuRgns );
- rgns = *menuRgns;
- tempRgn = NewRgn();
- RectRgn( tempRgn, sRect );
- theList = rgns->next;
- if( theList )
- {
- HLock( theList );
- DiffRgn( tempRgn, ( **theList ).theRgn, tempRgn );
- HUnlock( theList );
- }
- fixWindows( source, sRect, tempRgn, rgns->when );
- DisposeRgn( tempRgn );
- DisposeRgn( rgns->theRgn );
- HUnlock( menuRgns );
- DisposHandle( menuRgns );
- menuRgns = theList;
- }
- }
- }
-
- /*******************************************************
- * *
- * *
- *******************************************************/
-
- doCopyBits( mask, mode, dRect, sRect, dest, source ) /* reversed for pascal-ish-ness */
- BitMap *source, *dest;
- Rect *sRect, *dRect;
- int mode;
- RgnHandle mask;
- {
- int height;
-
- asm {
- movem.l d0-d7/a1-a5,-(sp)
- move.l CurrentA5,a5
- }
- if( !isMyCopy ) {
- startMyCopy();
- height = getMBarHeight() + 8;
- if( dRect->bottom - dRect->top >= height )
- fixCopy( source, dest, sRect, dRect, mode, mask );
- endMyCopy();
- }
- asm {
- movem.l (sp)+,d0-d7/a1-a5
- unlk a6
- move.l oldCopyBits,a0
- jmp (a0)
- }
- }
-
- startMyCopy() {
- ++isMyCopy;
- }
-
- endMyCopy() {
- --isMyCopy;
- }
-
- /*******************************************************
- * *
- * Sets the clipRgn of a window to its old clipRgn minus the part covered by the *
- * current menu region. This it gets out of the (global) stack of regions. *
- * *
- *******************************************************/
-
- doMenuClip( saveClip )
- RgnHandle saveClip;
- {
- Point off;
- RgnHandle newClip, theRgn;
-
- off = topLeft( thePort->portBits.bounds );
- GetClip( saveClip );
- if( menuRgns )
- {
- HLock( menuRgns );
- newClip = NewRgn();
- theRgn = ( **menuRgns ).theRgn;
- OffsetRgn( theRgn, off.h, off.v );
- DiffRgn( saveClip, theRgn, newClip );
- OffsetRgn( theRgn, -off.h, -off.v );
- SetClip( newClip );
- DisposeRgn( newClip );
- HUnlock( menuRgns );
- }
- }
-
- /*******************************************************
- * *
- * Doesn't care about params as it just installs some stuff when called. On the *
- * PopUpMenuSelect trap, the menu tracking hooks are installed, PopUp is called *
- * and the menu hooks are removed. This is an evil thing! However, this will *
- * probably never be tail patched by apple. To fix it, we need a reliable time to *
- * remove the menu hooks. *
- * Hmm - perhaps the menu hooks could be removed in the copyBits which *
- * restores the bits behind the topMost menu. Only trouble is with the update *
- * mechanism which is used for low-memory situations *
- * *
- *******************************************************/
-
- long pascal doPopUp( theMenu, top, left, item )
- MenuHandle theMenu;
- int top, left, item;
- {
- long result;
-
- asm {
- movem.l d0-d7/a1-a5,-(sp)
- move.l CurrentA5,a5
- }
- removePopUpTrap();
- installMenuTrap();
- asm {
- subq #4,sp
- move.l theMenu,-(sp)
- move top,-(sp)
- move left,-(sp)
- move item,-(sp)
- move.l oldPopUp,a0
- jsr (a0)
- move.l (sp)+,result
- }
- removeMenuTrap();
- installPopUpTrap();
- asm {
- movem.l (sp)+,d0-d7/a1-a5
- }
- return( result );
- }
-
- doSysMenu()
- {
- int temp;
- asm {
- movem.l d0-d7/a1-a5,-(sp)
- move.l CurrentA5,a5
- }
- removeMenuTrap();
- installModalTrap();
- sysMenuActed = 1;
- asm {
- move.l oldSysMenu,a0
- movem.l (sp)+,d0-d7/a1-a5
- unlk a6
- jmp (a0)
- }
- }
-
- /*******************************************************
- * *
- * *
- *******************************************************/
-
- installMenuTrap() {
- if( !menuTrapsOn ) {
- installWaitTrap();
- installDelayTrap();
- oldSysMenu = NGetTrapAddress( SysMenuTrapNum, ToolTrap );
- NSetTrapAddress( doSysMenu, SysMenuTrapNum, ToolTrap );
- oldCopyBits = NGetTrapAddress( CopyBitsTrapNum, ToolTrap );
- NSetTrapAddress( doCopyBits, CopyBitsTrapNum, ToolTrap );
- isMyCopy = 0;
- sysMenuActed = 0;
- }
- ++menuTrapsOn;
- }
-
- removeMenuTrap() {
- if( sysMenuActed ) {
- removeModalTrap();
- sysMenuActed = 0;
- } else {
- if( menuTrapsOn == 1 ) {
- NSetTrapAddress( oldCopyBits, CopyBitsTrapNum, ToolTrap );
- NSetTrapAddress( oldSysMenu, SysMenuTrapNum, ToolTrap );
- removeDelayTrap();
- removeWaitTrap();
- ++isMyCopy;
- }
- if( menuTrapsOn > 0 ) --menuTrapsOn;
- }
- }
-
- installPopUpTrap() {
- if( !popUpTrapOn ) {
- oldPopUp = NGetTrapAddress( PopUpTrapNum, ToolTrap );
- NSetTrapAddress( doPopUp, PopUpTrapNum, ToolTrap );
- }
- ++popUpTrapOn;
- }
-
- removePopUpTrap() {
- if( popUpTrapOn == 1 )
- NSetTrapAddress( oldPopUp, PopUpTrapNum, ToolTrap );
- if( popUpTrapOn > 0 ) --popUpTrapOn;
- }